home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Risc World 3
/
Risc World 3.iso
/
SOFTWARE
/
ISSUE6
/
PD
/
PDF
/
DrawFile
/
c++
/
GuiDrawFileRender
< prev
next >
Wrap
Text File
|
2003-02-14
|
12KB
|
390 lines
//--------------------------------------------------------------------------
//
// Copyright (c) 2002, Colin Granville
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or
// without modification, are permitted provided that the following
// conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// * The name Colin Granville may not be used to endorse or promote
// products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//--------------------------------------------------------------------------
#include <iostream.h>
#include "GuiDrawFileRender.h"
#include "DrawFileParser.h"
#include "DrawFileVisitor.h"
int mult(int a,int b) {return int(double(a)*double(b)/(1<<16));}
void matrixMult(const DrawFileVisitor::Transform& a,
const DrawFileVisitor::Transform& b,
DrawFileVisitor::Transform& res)
{
res.m0=mult(a.m0,b.m0)+mult(a.m1,b.m2); res.m1=mult(a.m0,b.m1)+mult(a.m1,b.m3);
res.m2=mult(a.m2,b.m0)+mult(a.m3,b.m2); res.m3=mult(a.m2,b.m1)+mult(a.m3,b.m3);
res.m4=res.m5=0;
}
void transform(const DrawFileVisitor::Transform& m,int x,int y,int& xr,int& yr)
{
xr=mult(x,m.m0)+mult(y,m.m2)+m.m4;
yr=mult(x,m.m1)+mult(y,m.m3)+m.m5;
}
class DrawParser: public DrawFileParser
{
public:
DrawParser(const GuiDrawFile& d) : draw(d) {}
virtual void* getObject(size_t start) const {return (void*)draw.getPtr(start);}
virtual size_t getSize() const {return draw.getSize();}
private:
const GuiDrawFile& draw;
};
//**************************************************************************
//**************************************************************************
//**************************************************************************
class Font
{
public:
Font(DrawFileParser& parser);
~Font();
void setTable(size_t start) {table=start;}
void find(int number,size_t width,size_t height);
private:
DrawFileParser& parser;
size_t table;
int number;
size_t width;
size_t height;
int handle;
int nameoffset;
};
//**************************************************************************
Font::Font(DrawFileParser& p)
: parser(p),
table(0),
number(-1),
handle(0),
nameoffset(1)
{
}
//**************************************************************************
Font::~Font()
{
if (handle) _swix(Font_LoseFont,_IN(0),handle);
}
//**************************************************************************
void Font::find(int n,size_t w,size_t h)
{
if (number==n && width==w && height==h) return;
unsigned char* start=(unsigned char*)parser.getObject(table);
unsigned char* p;
unsigned char num;
if (number==n)
{
p=start+nameoffset;
num=number;
}
else
{
p=start;
while (num=*p++,!(num==n || num==0))
{
while (*p!=0) p++;
p++;
}
nameoffset=p-start;
}
int oldHandle=handle;
int newHandle=0;
if (num==0 || _swix(Font_FindFont,_INR(1,5)|_OUT(0),(char*)p,w/40,h/40,0,0,&newHandle))
{
_swix(Font_FindFont,_INR(1,5)|_OUT(0),"Trinity.Medium",w/40,h/40,0,0,&newHandle);
}
if (newHandle)
{
if (oldHandle) _swix(Font_LoseFont,_IN(0),oldHandle);
handle=newHandle;
number=n;
width =w;
height=h;
}
}
//**************************************************************************
//**************************************************************************
//**************************************************************************
//**************************************************************************
class Renderer : public DrawFileVisitor
{
public:
Renderer(DrawFileParser& parser,
const DrawFileVisitor::Transform& t,
const GuiBBox& clipBox,
bool toPrinter);
~Renderer();
private:
DrawFileParser& parser;
const Transform& matrix;
GuiBBox clipBox;
Font font;
unsigned int blendFont;
virtual int fontTable(size_t start);
virtual int transformedTextObject(size_t start);
virtual int transformedSpriteObject(size_t start);
virtual int pathObject(size_t start);
};
//**************************************************************************
class Convert
{
public:
Convert(double* matrix) : ctm(matrix) {}
void convert(double x1, double y1, int& x2, int& y2)
{
x2 = (int)(ctm[0] * x1 + ctm[2] * y1);
y2 = (int)(ctm[1] * x1 + ctm[3] * y1);
}
private:
double* ctm;
};
inline void set(GuiBBox& b,int x,int y)
{
if (x<b.xmin) b.xmin=x;
if (x>b.xmax) b.xmax=x;
if (y<b.ymin) b.ymin=y;
if (y>b.ymax) b.ymax=y;
}
Renderer::Renderer(DrawFileParser& p,
const DrawFileVisitor::Transform& t,
const GuiBBox& c,
bool blend)
: parser(p),
matrix(t),
font(p),
blendFont(blend?(1<<11):0)
{
//transform bounding box using inverse matrix;
double m[4], im[4];
m[0]=((double)t.m0)/0x10000;
m[1]=((double)t.m1)/0x10000;
m[2]=((double)t.m2)/0x10000;
m[3]=((double)t.m3)/0x10000;
double det=1/(m[0]*m[3] - m[1]*m[2]);
im[0]=m[3]*det;
im[1]=-m[1]*det;
im[2]=-m[2]*det;
im[3]=m[0]*det;
Convert cvt(im);
int x,y;
cvt.convert(double(c.xmin*256-t.m4) ,double(c.ymin*256-t.m5),x,y);
clipBox.xmin=clipBox.xmax=x;
clipBox.ymin=clipBox.ymax=y;
cvt.convert(double(c.xmin*256-t.m4),double(c.ymax*256-t.m5),x,y);
set(clipBox,x,y);
cvt.convert(double(c.xmax*256-t.m4),double(c.ymax*256-t.m5),x,y);
set(clipBox,x,y);
cvt.convert(double(c.xmax*256-t.m4),double(c.ymin*256-t.m5),x,y);
set(clipBox,x,y);
};
//**************************************************************************
Renderer::~Renderer() {}
//**************************************************************************
int Renderer::fontTable(size_t start)
{
font.setTable(start+sizeof(DrawFileVisitor::FontTable));
return 1;
}
//**************************************************************************
int Renderer::transformedTextObject(size_t start)
{
DrawFileVisitor::TransformedTextObject& text=
*(DrawFileVisitor::TransformedTextObject*)parser.getObject(start);
if (!clipBox.overlap(text.bounds)) return 1;
font.find(text.font,text.fontXSize,text.fontYSize);
_swix(ColourTrans_SetFontColours,_INR(0,3),0,text.backColour,text.foreColour,14);
DrawFileVisitor::Transform res;
matrixMult(matrix,text.matrix,res);
int x,y;
transform(matrix,text.x,text.y,x,y);
_swix(Font_Paint,_INR(0,7),0,text.getText(),(1<<6)|(1<<8)|blendFont,x*25/16,y*25/16,0,&res,0);
return 1;
}
//**************************************************************************
int Renderer::transformedSpriteObject(size_t start)
{
DrawFileVisitor::TransformedSpriteObject* sprite=
(DrawFileVisitor::TransformedSpriteObject*)parser.getObject(start);
if (!clipBox.overlap(sprite->bounds)) return 1;
DrawFileVisitor::Transform res;
matrixMult(matrix,sprite->matrix,res);
transform(matrix,sprite->matrix.m4,sprite->matrix.m5,res.m4,res.m5);
int i;
int tableSize=0;
char* table=0;
for (i=0;i<2;i++)
{
sprite=(DrawFileVisitor::TransformedSpriteObject*)parser.getObject(start);
_swix(ColourTrans_SelectTable,_INR(0,5)|_OUT(4),
sprite->getSprite(),sprite->getSprite(),-1,-1,table,3|(1<<4),&tableSize);
if (i==1 || tableSize==0) break;
table=new char[tableSize];
if (!table) break;
}
_swix(OS_SpriteOp,_INR(0,7),0x200+56,
sprite->getSprite(),sprite->getSprite(),0,0,8 | (1<<5),&res,table);
delete [] table;
return 1;
}
//**************************************************************************
int Renderer::pathObject(size_t start)
{
DrawFileVisitor::PathObject& path=*(DrawFileVisitor::PathObject*)parser.getObject(start);
if (!clipBox.overlap(path.bounds)) return 1;
if (path.fillColour != -1)
{
_swix(ColourTrans_SetGCOL,_IN(0)|_INR(3,4),path.fillColour,0x100,0);
// size_t s=sizeof(DrawFileVisitor::PathObject);
// _swix(Draw_Fill,_INR(0,3),path.pathStart(),((path.pathStyle & (1<<6))?0x32:0x30),&matrix,0);
_swix(Draw_Fill,_INR(0,3),path.pathStart(),
((path.pathStyle & (1<<6))?0x32:0)/*0x3a:0x38)*/,&matrix,0);
if (path.outlineColour == -1 && blendFont)
{
// bodge to display areas which disappear on screen
// only do this for screen rendering
// blendFont <> 0 if drawing to screen
struct
{
unsigned int style;
int mitreJoin;
unsigned int leadCap;
unsigned int trailCap;
} capAndJoin;
capAndJoin.style=0x00010101;
capAndJoin.mitreJoin=0;
capAndJoin.leadCap=0;
capAndJoin.trailCap=capAndJoin.leadCap;
_swix(Draw_Stroke,_INR(0,6),path.pathStart(),0,&matrix,0,0,&capAndJoin,0);
}
}
if (path.outlineColour != -1)
{
_swix(ColourTrans_SetGCOL,_IN(0)|_INR(3,4),path.outlineColour,0x100,0);
struct
{
unsigned int style;
int mitreJoin;
unsigned int leadCap;
unsigned int trailCap;
} capAndJoin;
capAndJoin.style= ( (path.pathStyle & 3) |
(((path.pathStyle>>4) & 3)<<8) |
(((path.pathStyle>>2) & 3)<<16) );
capAndJoin.leadCap=( (path.capWidth*16) | ((path.capHeight*16)<<16) );
capAndJoin.trailCap=capAndJoin.leadCap;
// capAndJoin.mitreJoin=((path.outlineWidth*4)<<8);
capAndJoin.mitreJoin=8<<16;
_swix(Draw_Stroke,_INR(0,6),path.pathStart(),0x38,&matrix,0,
path.outlineWidth,&capAndJoin,
path.dashStart());
}
return 1;
}
//**************************************************************************
//**************************************************************************
//**************************************************************************
_kernel_oserror* GuiDrawFile_render(const GuiDrawFile& draw,
const DrawFileVisitor::Transform* mat,
const GuiBBox* clipBox,
bool blendFonts)
{
static GuiBBox defClipBox={0,0,0x7fff,0x7fff};
static DrawFileVisitor::Transform defMatrix={(1<<16),0,0,(1<<16),0,0};
DrawParser drawfile(draw);
Renderer renderer(drawfile,
*(mat?mat:&defMatrix),
*(clipBox?clipBox:&defClipBox),
blendFonts);
drawfile.accept(renderer);
//DrawFile_Render
//return _swix(0x45540,_INR(0,5),0,draw.getPtr(0),size,
// (mat?mat:&defMatrix),(clipBox?clipBox:&defClipBox),0);
return 0;
};